﻿using ElasticAgTest.Common.Extensions;
using ElasticAgTest.Models;
using OxyPlot;
using OxyPlot.Series;
using Prism.Commands;
using Prism.Events;
using Prism.Ioc;
using Prism.Regions;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using MathNet.Numerics;
using MathNet.Numerics.Distributions;
using OxyPlot.Axes;
using System.Data;
using System.IO;
using Newtonsoft.Json;
using System.Windows.Forms;
using CsvHelper;
using System.Globalization;
using ElasticAgTest.Common;
using MaterialDesignThemes.Wpf;
using System.Windows.Media.Imaging;

namespace ElasticAgTest.ViewModels
{
    public class IndexViewModel : NavigationViewModel
    {
        #region 变量
        private readonly IEventAggregator aggregator;
        private readonly IDialogHostService _dialogHostService;
        bool pAlarmFlag = false, readyFlag = false;
        ConcurrentQueue<MData> fifoQueue = new ConcurrentQueue<MData>();
        CancellationTokenSource source1;
        CancellationTokenSource source2;
        AutoResetEvent WaitReceiveOne = new AutoResetEvent(false);
        List<MData> MDataStatisticsList = new List<MData>();
        List<double> KList = new List<double>();
        Param param;
        int debugXAxisIndex = 0;
        double ZeroValue;
        bool recordZeroFlag = false;
        bool isLogin = false;
        string curCSVFileName = "";
        bool PLCFinishFlag = false;
        //string curScreenShotFile = "";
        //DateTime lastScreenShotTime = DateTime.Now;
        double topva = 0;
        OxyColor foreground;
        PlotModel PlotModel100;
        #endregion
        #region 属性
        private int opeMode = 0;
        public int OpeMode
        {
            get { return opeMode; }
            set { SetProperty(ref opeMode, value); }
        }
        private int cmdCount;
        public int CmdCount
        {
            get { return cmdCount; }
            set {
                int va = value;
                if (value < CountLowLimit)
                {
                    va = CountLowLimit;
                }
                else if (value > CountHighLimit)
                {
                    va = CountHighLimit;
                }
                SetProperty(ref cmdCount, va);
            }
        }
        private float cmdDistance;
        public float CmdDistance
        {
            get { return cmdDistance; }
            set {
                float va = value;
                if (value < DistanceLowLimit)
                {
                    va = DistanceLowLimit;
                }
                if (value > DistanceHighLimit)
                {
                    va = DistanceHighLimit;
                }
                SetProperty(ref cmdDistance, va); }
        }
        private double cmdSpeed;
        public double CmdSpeed
        {
            get { return cmdSpeed; }
            set {
                double va = value;
                if (value < SpeedLowLimit)
                {
                    va = SpeedLowLimit;
                }
                if (value > SpeedHighLimit)
                {
                    va = SpeedHighLimit;
                }
                SetProperty(ref cmdSpeed, va); }
        }
        private int cmdCount_Debug;
        public int CmdCount_Debug
        {
            get { return cmdCount_Debug; }
            set {
                int va = value;
                if (value < 1)
                {
                    va = 1;
                }
                else if (value > 100)
                {
                    va = 100;
                }
                SetProperty(ref cmdCount_Debug, va); }
        }
        private double progressBarValue;
        public double ProgressBarValue
        {
            get { return progressBarValue; }
            set { SetProperty(ref progressBarValue, value); }
        }
        private int curCount;
        public int CurCount
        {
            get { return curCount; }
            set { SetProperty(ref curCount, value); }
        }
        private int totalCount;
        public int TotalCount
        {
            get { return totalCount; }
            set { SetProperty(ref totalCount, value); }
        }
        private PlotModel plotModel1;
        public PlotModel PlotModel1
        {
            get { return plotModel1; }
            set { SetProperty(ref plotModel1, value); }
        }
        private PlotModel plotModel2;
        public PlotModel PlotModel2
        {
            get { return plotModel2; }
            set { SetProperty(ref plotModel2, value); }
        }
        private bool runStartFlag;
        public bool RunStartFlag
        {
            get { return runStartFlag; }
            set { SetProperty(ref runStartFlag, value); }
        }

        private bool runButtonIsEnable;
        public bool RunButtonIsEnable
        {
            get { return runButtonIsEnable; }
            set { SetProperty(ref runButtonIsEnable, value); }
        }
        private bool radioButtonIsEnable1;
        public bool RadioButtonIsEnable1
        {
            get { return radioButtonIsEnable1; }
            set { SetProperty(ref radioButtonIsEnable1, value); }
        }
        private bool radioButtonIsEnable2;
        public bool RadioButtonIsEnable2
        {
            get { return radioButtonIsEnable2; }
            set { SetProperty(ref radioButtonIsEnable2, value); }
        }
        private DataTable pointData;
        public DataTable PointData
        {
            get { return pointData; }
            set { SetProperty(ref pointData, value); }
        }
        private double startPos;
        public double StartPos
        {
            get { return startPos; }
            set {
                double va = value;
                if (value < 0)
                {
                    va = 0;
                }
                if (value > 2)
                {
                    va = 2;
                }
                SetProperty(ref startPos, va); }
        }
        private double endPos;
        public double EndPos
        {
            get { return endPos; }
            set {
                double va = value;
                if (value < startPos)
                {
                    va = startPos;
                }
                if (value > 2)
                {
                    va = 2;
                }
                SetProperty(ref endPos, va); }
        }
        private string testModeVisibility = "Visible";
        public string TestModeVisibility
        {
            get { return testModeVisibility; }
            set { SetProperty(ref testModeVisibility, value); }
        }
        private string debugModeVisibility = "Collapsed";
        public string DebugModeVisibility
        {
            get { return debugModeVisibility; }
            set { SetProperty(ref debugModeVisibility, value); }
        }
        private bool run_DeubgStartFlag;
        public bool Run_DeubgStartFlag
        {
            get { return run_DeubgStartFlag; }
            set { SetProperty(ref run_DeubgStartFlag, value); }
        }
        private bool run_DeubgButtonIsEnable;
        public bool Run_DeubgButtonIsEnable
        {
            get { return run_DeubgButtonIsEnable; }
            set { SetProperty(ref run_DeubgButtonIsEnable, value); }
        }
        private double instantForce;
        public double InstantForce
        {
            get { return instantForce; }
            set { SetProperty(ref instantForce, value); }
        }
        private double instantPos;
        public double InstantPos
        {
            get { return instantPos; }
            set { SetProperty(ref instantPos, value); }
        }
        private bool runPauseFlag;
        public bool RunPauseFlag
        {
            get { return runPauseFlag; }
            set { SetProperty(ref runPauseFlag, value); }
        }
        private bool pauseButtonIsEnable;
        public bool PauseButtonIsEnable
        {
            get { return pauseButtonIsEnable; }
            set { SetProperty(ref pauseButtonIsEnable, value); }
        }
        private DateTime finishedClock = DateTime.Now;
        public DateTime FinishedClock
        {
            get { return finishedClock; }
            set { SetProperty(ref finishedClock, value); }
        }
        private string instantValueVisibility;
        public string InstantValueVisibility
        {
            get { return instantValueVisibility; }
            set { SetProperty(ref instantValueVisibility, value); }
        }
        private PlotModel plotModel11;
        public PlotModel PlotModel11
        {
            get { return plotModel11; }
            set { SetProperty(ref plotModel11, value); }
        }
        private PlotModel plotModel12;
        public PlotModel PlotModel12
        {
            get { return plotModel12; }
            set { SetProperty(ref plotModel12, value); }
        }
        private PlotModel plotModel13;
        public PlotModel PlotModel13
        {
            get { return plotModel13; }
            set { SetProperty(ref plotModel13, value); }
        }
        private PlotModel plotModel14;
        public PlotModel PlotModel14
        {
            get { return plotModel14; }
            set { SetProperty(ref plotModel14, value); }
        }
        private PlotModel plotModel15;
        public PlotModel PlotModel15
        {
            get { return plotModel15; }
            set { SetProperty(ref plotModel15, value); }
        }
        private PlotModel plotModel16;
        public PlotModel PlotModel16
        {
            get { return plotModel16; }
            set { SetProperty(ref plotModel16, value); }
        }
        private PlotModel plotModel17;
        public PlotModel PlotModel17
        {
            get { return plotModel17; }
            set { SetProperty(ref plotModel17, value); }
        }
        private PlotModel plotModel18;
        public PlotModel PlotModel18
        {
            get { return plotModel18; }
            set { SetProperty(ref plotModel18, value); }
        }
        private PlotModel plotModel19;
        public PlotModel PlotModel19
        {
            get { return plotModel19; }
            set { SetProperty(ref plotModel19, value); }
        }
        private PlotModel plotModel20;
        public PlotModel PlotModel20
        {
            get { return plotModel20; }
            set { SetProperty(ref plotModel20, value); }
        }
        private string homeViewVisibility;
        public string HomeViewVisibility
        {
            get { return homeViewVisibility; }
            set { SetProperty(ref homeViewVisibility, value); }
        }
        private string lifetimeViewVisibility;
        public string LifetimeViewVisibility
        {
            get { return lifetimeViewVisibility; }
            set { SetProperty(ref lifetimeViewVisibility, value); }
        }
        private string historyViewVisibility;
        public string HistoryViewVisibility
        {
            get { return historyViewVisibility; }
            set { SetProperty(ref historyViewVisibility, value); }
        }
        private string settingsViewVisibility;
        public string SettingsViewVisibility
        {
            get { return settingsViewVisibility; }
            set { SetProperty(ref settingsViewVisibility, value); }
        }
        
        private bool _isDarkTheme;
        public bool IsDarkTheme
        {
            get { return _isDarkTheme; }
            set
            {
                if (SetProperty(ref _isDarkTheme, value))
                {
                    ModifyTheme(theme => theme.SetBaseTheme(value ? Theme.Light : Theme.Dark));
                    ApplyTheme(value);
                }
            }
        }
        private int countLowLimit;
        public int CountLowLimit
        {
            get { return countLowLimit; }
            set {
                int va = value;
                if (value < 1)
                {
                    va = 1;
                }
                else if (value > countHighLimit)
                {
                    va = countHighLimit - 1;
                }
                if (va < 1)
                {
                    va = 1;
                }
                SetProperty(ref countLowLimit, va); }
        }
        private int countHighLimit;
        public int CountHighLimit
        {
            get { return countHighLimit; }
            set {
                int va = value;
                if (value > 1500000)
                {
                    va = 1500000;
                }
                else if (value < countLowLimit)
                {
                    va = countLowLimit + 1;
                }
                if (va > 1500000)
                {
                    va = 1500000;
                }
                SetProperty(ref countHighLimit, va); }
        }
        private float distanceLowLimit;
        public float DistanceLowLimit
        {
            get { return distanceLowLimit; }
            set {
                float va = value;
                if (value < 0.1)
                {
                    va = (float)0.1;
                }
                else if (value > distanceHighLimit)
                {
                    va = (float)(distanceHighLimit - 0.1);
                }
                if (va < 0.1)
                {
                    va = (float)0.1;
                }
                SetProperty(ref distanceLowLimit, va); }
        }
        private float distanceHighLimit;
        public float DistanceHighLimit
        {
            get { return distanceHighLimit; }
            set {
                float va = value;
                if (value > 2.0)
                {
                    va = (float)2.0;
                }
                else if (value < distanceLowLimit)
                {
                    va = (float)(distanceLowLimit + 0.1);
                }
                if (va > 2.0)
                {
                    va = (float)2.0;
                }
                SetProperty(ref distanceHighLimit, va); }
        }
        private double speedLowLimit;
        public double SpeedLowLimit
        {
            get { return speedLowLimit; }
            set {
                double va = value;
                if (value < 0.1)
                {
                    va = 0.1;
                }
                else if (value > speedHighLimit)
                {
                    va = speedHighLimit - 1;
                }
                if (va < 0.1)
                {
                    va = 0.1;
                }
                SetProperty(ref speedLowLimit, va); }
        }
        private double speedHighLimit;
        public double SpeedHighLimit
        {
            get { return speedHighLimit; }
            set {
                double va = value;
                if (value > 10.0)
                {
                    va = 10.0;
                }
                else if (value < speedLowLimit)
                {
                    va = speedLowLimit + 1;
                }
                if (va > 10.0)
                {
                    va = 10.0;
                }
                SetProperty(ref speedHighLimit, va); }
        }
        private BitmapSource imageSource100;
        public BitmapSource ImageSource100
        {
            get { return imageSource100; }
            set { SetProperty(ref imageSource100, value); }
        }
        private bool servoOnFlag;
        public bool ServoOnFlag
        {
            get { return servoOnFlag; }
            set { SetProperty(ref servoOnFlag, value); }
        }
        #endregion
        #region 方法绑定
        private DelegateCommand<object> opeModeCommand;
        public DelegateCommand<object> OpeModeCommand =>
            opeModeCommand ?? (opeModeCommand = new DelegateCommand<object>(ExecuteOpeModeCommand));
        private DelegateCommand runCommand;
        public DelegateCommand RunCommand =>
            runCommand ?? (runCommand = new DelegateCommand(ExecuteRunCommand));
        private DelegateCommand run_DeubgCommand;
        public DelegateCommand Run_DeubgCommand =>
            run_DeubgCommand ?? (run_DeubgCommand = new DelegateCommand(ExecuteRun_DeubgCommand));
        private DelegateCommand cleanActionCommand;
        public DelegateCommand CleanActionCommand =>
            cleanActionCommand ?? (cleanActionCommand = new DelegateCommand(ExecuteCleanActionCommand));
        private DelegateCommand pauseCommand;
        public DelegateCommand PauseCommand =>
            pauseCommand ?? (pauseCommand = new DelegateCommand(ExecutePauseCommand));
        private DelegateCommand cleanAllRecordCommand;
        public DelegateCommand CleanAllRecordCommand =>
            cleanAllRecordCommand ?? (cleanAllRecordCommand = new DelegateCommand(ExecuteCleanAllRecordCommand));
        private DelegateCommand setZeroPosCommand;
        public DelegateCommand SetZeroPosCommand =>
            setZeroPosCommand ?? (setZeroPosCommand = new DelegateCommand(ExecuteSetZeroPosCommand));
        private DelegateCommand<object> servoOnCommand;
        public DelegateCommand<object> ServoOnCommand =>
            servoOnCommand ?? (servoOnCommand = new DelegateCommand<object>(ExecuteServoOnCommand));

        void ExecuteServoOnCommand(object obj)
        {
            if (PLCModbus.Instance.Connected)
            {
                PLCModbus.Instance.WriteMCoil(450, !(bool)obj);
            }
        }
        async void ExecuteSetZeroPosCommand()
        {
            var dialogResult = await _dialogHostService.Question("温馨提示", "确认设置电气零点吗?");
            if (dialogResult.Result == Prism.Services.Dialogs.ButtonResult.OK)
            {
                if (PLCModbus.Instance.Connected)
                {
                    PLCModbus.Instance.WriteMCoil(501, true);
                }
            }
        }
        async void ExecuteCleanAllRecordCommand()
        {
            var dialogResult = await _dialogHostService.Question("温馨提示", "确认删除所有测试记录吗?");
            if (dialogResult.Result == Prism.Services.Dialogs.ButtonResult.OK)
            {
                if (!RunStartFlag)
                {
                    //删除文件夹
                    System.IO.DirectoryInfo di1 = new System.IO.DirectoryInfo(System.IO.Path.Combine(param.CsvSavePath, "Point"));
                    System.IO.DirectoryInfo di2 = new System.IO.DirectoryInfo(System.IO.Path.Combine(param.ScreenShotSavePath, "ScreenShot"));
                    // Delete this dir and all subdirs.
                    try
                    {
                        if (di1.Exists)
                        {
                            di1.Delete(true);
                        }
                        if (di2.Exists)
                        {
                            di2.Delete(true);                            
                        }
                        di1.Create();
                        di2.Create();
                        aggregator.SendMessage("清空完成!");
                    }
                    catch (System.IO.IOException ex)
                    {
                        MessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    }  
                }
                else
                {
                    await _dialogHostService.Question("警告", "正在测试，不能进行清空。", false);
                }
            }
        }
        void ExecutePauseCommand()
        {
            if (PLCModbus.Instance.Connected)
            {
                TotalCount = CmdCount;
                //次数，双字整型
                string _CmdCountStr = CmdCount.ToString("X8");
                ushort[] _CmdCount = new ushort[2] { Convert.ToUInt16(_CmdCountStr.Substring(4, 4), 16), Convert.ToUInt16(_CmdCountStr.Substring(0, 4), 16) };
                PLCModbus.Instance.WritRegisters(7000, _CmdCount);

                //速度
                var speed = (float)(CmdSpeed * CmdDistance / 2 * 90 / 0.1 / 2);
                byte[] _speedArr = BitConverter.GetBytes(speed);
                string _speedStr = _speedArr[3].ToString("X2") + _speedArr[2].ToString("X2") + _speedArr[1].ToString("X2") + _speedArr[0].ToString("X2");
                ushort[] _speed = new ushort[2] { Convert.ToUInt16(_speedStr.Substring(4, 4), 16), Convert.ToUInt16(_speedStr.Substring(0, 4), 16) };
                PLCModbus.Instance.WritRegisters(5004, _speed);

                PLCModbus.Instance.WriteMCoil(1001, RunPauseFlag);

            }
            if (MCUSerial.Instance.Connected)
            {
                if (RunStartFlag)
                {
                    MCUSerial.Instance.WriteMCURegister(40001, RunPauseFlag ? 0 : 1);
                }
            }
        }
        void ExecuteCleanActionCommand()
        {
            recordZeroFlag = true;
            if (MCUSerial.Instance.Connected)
            {
                MCUSerial.Instance.WriteMCURegister(40002, 0);
            }
        }
        async void ExecuteRun_DeubgCommand()
        {
            try
            {
                if (Run_DeubgStartFlag)
                {
                    var dialogResult = await _dialogHostService.Question("请确认", $"以 速度:{CmdSpeed}次/秒 行程:{CmdDistance}mm \n运动吗？");
                    if (dialogResult.Result == Prism.Services.Dialogs.ButtonResult.OK)
                    {
                        RadioButtonIsEnable2 = false;
                        RadioButtonIsEnable1 = false;
                        InstantValueVisibility = "Collapsed";
                        if (source2 != null)
                        {
                            source2.Cancel();
                            await Task.Delay(500);
                        }
                        PlotModel1 = new PlotModel { Title = "弹力曲线", TitleColor = foreground };
                        PlotModel1.PlotAreaBorderColor = foreground;
                        PlotModel1.TextColor = foreground;
                        PlotModel1.Axes.Add(new LinearAxis { Position = AxisPosition.Bottom, MajorGridlineStyle = LineStyle.Dot, MajorGridlineColor = foreground, Title = "Pos", TitleFontSize = 16, Minimum = 0, Maximum = EndPos - StartPos, TicklineColor = foreground });
                        PlotModel1.Axes.Add(new LinearAxis { Position = AxisPosition.Left, MajorGridlineStyle = LineStyle.Dot, MajorGridlineColor = foreground, Title = "Weight（gf）", TitleFontSize = 16, TicklineColor = foreground });
                        PlotModel1.InvalidatePlot(true);
                        PointData = null;
                        MDataStatisticsList.Clear();
                        KList.Clear();
                        PlotModel2.Axes.Clear();
                        PlotModel2.Series.Clear();
                        PlotModel2.InvalidatePlot(true);

                        TotalCount = CmdCount;
                        if (StartPos >= CmdDistance)
                        {
                            StartPos = 0;
                        }
                        if (EndPos > CmdDistance + 0.2)
                        {
                            EndPos = CmdDistance + 0.2;
                        }
                        TotalCount = CmdCount_Debug;
                        //次数，双字整型
                        string _CmdCountStr = CmdCount_Debug.ToString("X8");
                        ushort[] _CmdCount = new ushort[2] { Convert.ToUInt16(_CmdCountStr.Substring(4, 4), 16), Convert.ToUInt16(_CmdCountStr.Substring(0, 4), 16) };
                        PLCModbus.Instance.WritRegisters(7000, _CmdCount);

                        //行程
                        var distD = CmdDistance / 2 * 90;
                        var distR = 0;
                        byte[] _distDByteArr = BitConverter.GetBytes(distD);
                        string _distDStr = _distDByteArr[3].ToString("X2") + _distDByteArr[2].ToString("X2") + _distDByteArr[1].ToString("X2") + _distDByteArr[0].ToString("X2");
                        ushort[] _distD = new ushort[2] { Convert.ToUInt16(_distDStr.Substring(4, 4), 16), Convert.ToUInt16(_distDStr.Substring(0, 4), 16) };
                        PLCModbus.Instance.WritRegisters(4004, _distD);

                        byte[] _distRByteArr = BitConverter.GetBytes(distR);
                        string _distRStr = _distRByteArr[3].ToString("X2") + _distRByteArr[2].ToString("X2") + _distRByteArr[1].ToString("X2") + _distRByteArr[0].ToString("X2");
                        ushort[] _distR = new ushort[2] { Convert.ToUInt16(_distRStr.Substring(4, 4), 16), Convert.ToUInt16(_distRStr.Substring(0, 4), 16) };
                        PLCModbus.Instance.WritRegisters(4006, _distR);

                        //速度
                        var speed = (float)(CmdSpeed * CmdDistance / 2 * 90 / 0.1 / 2);
                        byte[] _speedArr = BitConverter.GetBytes(speed);
                        string _speedStr = _speedArr[3].ToString("X2") + _speedArr[2].ToString("X2") + _speedArr[1].ToString("X2") + _speedArr[0].ToString("X2");
                        ushort[] _speed = new ushort[2] { Convert.ToUInt16(_speedStr.Substring(4, 4), 16), Convert.ToUInt16(_speedStr.Substring(0, 4), 16) };
                        PLCModbus.Instance.WritRegisters(5004, _speed);
                        PLCModbus.Instance.WriteMCoil(10, false);
                        PLCModbus.Instance.WriteMCoil(12, true);
                        MCUSerial.Instance.WriteMCURegister(40001, 1);
                    }
                    else
                    {
                        Run_DeubgStartFlag = false;
                    }
                  
                }
                else
                {
                    bool configflag = false;
                    if (CurCount < TotalCount)
                    {
                        var dialogResult = await _dialogHostService.Question("温馨提示", "确认中止测试吗?");
                        if (dialogResult.Result == Prism.Services.Dialogs.ButtonResult.OK)
                        {
                            configflag = true;
                        }
                    }
                    else
                    {
                        configflag = true;
                    }
                    if (configflag)
                    {
                        RadioButtonIsEnable1 = true;
                        InstantValueVisibility = "Visible";
                        source2 = new CancellationTokenSource();
                        CancellationToken token1 = source2.Token;
                        PlotModel1 = new PlotModel();
                        PlotModel1.PlotAreaBorderColor = foreground;
                        PlotModel1.TextColor = foreground;
                        PlotModel1.Series.Add(new LineSeries { LineStyle = LineStyle.Solid, Color = OxyColors.SpringGreen, TrackerFormatString = "{0}\n{1}: {2:f0}\n{3}: {4:0.0}" });
                        PlotModel1.Axes.Add(new LinearAxis { Position = AxisPosition.Bottom,  MajorGridlineStyle = LineStyle.Dot, MajorGridlineColor = foreground, Title = "Index", TitleFontSize = 16, TicklineColor = foreground });
                        PlotModel1.Axes.Add(new LinearAxis { Position = AxisPosition.Left,  MajorGridlineStyle = LineStyle.Dot, MajorGridlineColor = foreground, Title = "Weight（gf）", TitleFontSize = 16, Minimum = -100, Maximum = 600, TicklineColor = foreground });
                        PlotModel1.InvalidatePlot(true);
                        Task.Run(() => DebugRun(token1), token1);

                        PLCModbus.Instance.WriteMCoil(12, false);
                        MCUSerial.Instance.WriteMCURegister(40001, 0);
                        RadioButtonIsEnable2 = true;
                    }
                    else
                    {
                        Run_DeubgStartFlag = true;
                    }
                }

            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
            }
        }
        async void ExecuteRunCommand()
        {
            try
            {
                if (RunStartFlag)
                {
                    var dialogResult = await _dialogHostService.Question("请确认", $"以 速度:{CmdSpeed}次/秒 行程:{CmdDistance}mm \n运动吗？");
                    if (dialogResult.Result == Prism.Services.Dialogs.ButtonResult.OK)
                    {                        
                        RadioButtonIsEnable1 = false;
                        RadioButtonIsEnable2 = false;
                        PlotModel1.Series.Clear();
                        var s1 = new LineSeries
                        {
                            //LineStyle = LineStyle.Solid,
                            //Color = OxyColors.SpringGreen
                            StrokeThickness = 0,
                            MarkerSize = 1,
                            MarkerStroke = OxyColors.ForestGreen,
                            MarkerType = MarkerType.Square,
                            TrackerFormatString = "{0}\n{1}: {2:0.000}\n{3}: {4:0.0}"
                        };
                        PlotModel1.Series.Add(s1);
                        PlotModel1.InvalidatePlot(true);
                        PointData = null;
                        MDataStatisticsList.Clear();
                        KList.Clear();
                        PlotModel2.Axes.Clear();
                        PlotModel2.Series.Clear();
                        PlotModel2.InvalidatePlot(true);

                        TotalCount = CmdCount;
                        if (StartPos >= CmdDistance)
                        {
                            StartPos = 0;
                        }
                        if (EndPos > CmdDistance + 0.2)
                        {
                            EndPos = CmdDistance + 0.2;
                        }

                        int mCount1 = 10;
                        double div1 = (EndPos - StartPos) / (mCount1 - 1);
                        Init10Oxy(0, div1);

                        PlotModel100.Series.Clear();
                        GC.Collect();
                        var pngExporter = new OxyPlot.Wpf.PngExporter { Width = 1280, Height = 660 };
                        ImageSource100 = pngExporter.ExportToBitmap(PlotModel100);
                        curCSVFileName = $"Point{ DateTime.Now:yyyyMMddHHmmss}.csv";
                        DirectoryInfo dir = new DirectoryInfo(Path.Combine(param.CsvSavePath, "Point"));
                        if (!dir.Exists)
                        {
                            Directory.CreateDirectory(Path.Combine(param.CsvSavePath, "Point"));
                        }
                        //次数，双字整型
                        string _CmdCountStr = CmdCount.ToString("X8");
                        ushort[] _CmdCount = new ushort[2] { Convert.ToUInt16(_CmdCountStr.Substring(4, 4), 16), Convert.ToUInt16(_CmdCountStr.Substring(0, 4), 16) };
                        PLCModbus.Instance.WritRegisters(7000, _CmdCount);

                        //行程
                        var distD = CmdDistance / 2 * 90;
                        var distR = 0;
                        byte[] _distDByteArr = BitConverter.GetBytes(distD);
                        string _distDStr = _distDByteArr[3].ToString("X2") + _distDByteArr[2].ToString("X2") + _distDByteArr[1].ToString("X2") + _distDByteArr[0].ToString("X2");
                        ushort[] _distD = new ushort[2] { Convert.ToUInt16(_distDStr.Substring(4, 4), 16), Convert.ToUInt16(_distDStr.Substring(0, 4), 16) };
                        PLCModbus.Instance.WritRegisters(4004, _distD);

                        byte[] _distRByteArr = BitConverter.GetBytes(distR);
                        string _distRStr = _distRByteArr[3].ToString("X2") + _distRByteArr[2].ToString("X2") + _distRByteArr[1].ToString("X2") + _distRByteArr[0].ToString("X2");
                        ushort[] _distR = new ushort[2] { Convert.ToUInt16(_distRStr.Substring(4, 4), 16), Convert.ToUInt16(_distRStr.Substring(0, 4), 16) };
                        PLCModbus.Instance.WritRegisters(4006, _distR);

                        //速度
                        var speed = (float)(CmdSpeed * CmdDistance / 2 * 90 / 0.1 / 2);
                        byte[] _speedArr = BitConverter.GetBytes(speed);
                        string _speedStr = _speedArr[3].ToString("X2") + _speedArr[2].ToString("X2") + _speedArr[1].ToString("X2") + _speedArr[0].ToString("X2");
                        ushort[] _speed = new ushort[2] { Convert.ToUInt16(_speedStr.Substring(4, 4), 16), Convert.ToUInt16(_speedStr.Substring(0, 4), 16) };
                        PLCModbus.Instance.WritRegisters(5004, _speed);
                        PLCModbus.Instance.WriteMCoil(10, false);
                        PLCModbus.Instance.WriteMCoil(12, true);
                        MCUSerial.Instance.WriteMCURegister(40001, 1);
                        PLCFinishFlag = false;
                    }
                    else
                    {
                        RunStartFlag = false;
                    }
                }
                else
                {
                    bool configflag = false;
                    if (CurCount < TotalCount)
                    {
                        var dialogResult = await _dialogHostService.Question("温馨提示", "确认中止测试吗?");
                        if (dialogResult.Result == Prism.Services.Dialogs.ButtonResult.OK)
                        {
                            configflag = true;
                        }
                    }
                    else
                    {
                        configflag = true;
                    }
                    if (configflag)
                    {
                        if (isLogin)
                        {
                            RadioButtonIsEnable2 = true;
                        }
                        if (RunPauseFlag)
                        {
                            RunPauseFlag = false;
                            if (PLCModbus.Instance.Connected)
                            {
                                PLCModbus.Instance.WriteMCoil(1001, RunPauseFlag);
                            }
                        }
                        //存CSV
                        //CSVSave();
                        switch (OpeMode)
                        {
                            case 2:

                                source2 = new CancellationTokenSource();
                                CancellationToken token1 = source2.Token;
                                PlotModel1 = new PlotModel();
                                PlotModel1.PlotAreaBorderColor = foreground;
                                PlotModel1.TextColor = foreground;
                                PlotModel1.Series.Add(new LineSeries { LineStyle = LineStyle.Solid, Color = OxyColors.SpringGreen, TrackerFormatString = "{0}\n{1}: {2:f0}\n{3}: {4:0.0}" });
                                PlotModel1.Axes.Add(new LinearAxis { Position = AxisPosition.Bottom,  MajorGridlineStyle = LineStyle.Dot, MajorGridlineColor = foreground, Title = "Index", TitleFontSize = 16, TicklineColor = foreground });
                                PlotModel1.Axes.Add(new LinearAxis { Position = AxisPosition.Left,  MajorGridlineStyle = LineStyle.Dot, MajorGridlineColor = foreground, Title = "Weight（gf）", TitleFontSize = 16, Minimum = -100, Maximum = 600, TicklineColor = foreground });
                                PlotModel1.InvalidatePlot(true);
                                Task.Run(() => DebugRun(token1), token1);
                                break;
                            default:
                                break;
                        }
                        PLCModbus.Instance.WriteMCoil(12, false);
                        MCUSerial.Instance.WriteMCURegister(40001, 0);

                        RadioButtonIsEnable1 = true;
                    }
                    else
                    {
                        RunStartFlag = true;
                    }
                }
                
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
            }  
        }
        void ExecuteOpeModeCommand(object obj)
        {
            if (OpeMode != int.Parse(obj.ToString()))
            {
                if (source2 != null)
                {
                    source2.Cancel();
                }
                OperateModeAciton(int.Parse(obj.ToString()));
                OpeMode = int.Parse(obj.ToString());
            }
        }
        #endregion
        #region 导航
        public override void OnNavigatedFrom(NavigationContext navigationContext)
        {
            
        }
        public override void OnNavigatedTo(NavigationContext navigationContext)
        {

        }
        #endregion
        #region 构造函数
        public IndexViewModel(IContainerProvider containerProvider, IDialogHostService dialogHostService) : base(containerProvider)
        {
            _dialogHostService = dialogHostService;
            LoadParam();
            CountLowLimit = param.CountLowLimit;
            CountHighLimit = param.CountHighLimit;
            DistanceLowLimit = param.DistanceLowLimit;
            DistanceHighLimit = param.DistanceHighLimit;
            SpeedLowLimit = param.SpeedLowLimit;
            SpeedHighLimit = param.SpeedHighLimit;
            StartPos = param.StartPos;
            EndPos = param.EndPos;
            ZeroValue = param.ZeroValue;
            foreground = param.IsDarkTheme ? OxyColor.FromRgb(32, 32, 32) : OxyColors.White;
            IsDarkTheme = param.IsDarkTheme;
            int mCount1 = 10;
            double div1 = (EndPos - StartPos) / (mCount1 - 1);
            Init10Oxy(0, div1);
            //数量
            TotalCount = CmdCount = param.CmdCount;
            CmdCount_Debug = param.CmdCount_Debug;
            //距离
            CmdDistance = param.CmdDistance;
            //速度
            CmdSpeed = param.CmdSpeed;
            PlotModel2 = new PlotModel { Title = "K值统计", TitleColor = foreground};
            PlotModel2.PlotAreaBorderColor = foreground;
            PlotModel2.TextColor = foreground;
            PlotModel2.InvalidatePlot(true);
            PlotModel100 = new PlotModel() { Title = "历史曲线", TitleColor = foreground };
            PlotModel100.PlotAreaBorderColor = foreground;
            PlotModel100.TextColor = foreground;
            PlotModel100.Axes.Add(new LinearAxis { Position = AxisPosition.Bottom, MajorGridlineStyle = LineStyle.Dot, MajorGridlineColor = foreground, Title = "Pos(mm)", TitleFontSize = 16, TicklineColor = foreground });
            PlotModel100.Axes.Add(new LinearAxis { Position = AxisPosition.Left, MajorGridlineStyle = LineStyle.Dot, MajorGridlineColor = foreground, Title = "Weight（gf）", TitleFontSize = 16, TicklineColor = foreground });
            
            var pngExporter = new OxyPlot.Wpf.PngExporter { Width = 1280, Height = 660 };
            ImageSource100 = pngExporter.ExportToBitmap(PlotModel100);

            aggregator = containerProvider.Resolve<IEventAggregator>();
            InstantValueVisibility = "Collapsed";
            aggregator.ResgiterMessage(async arg =>
            {
                try
                {
                    switch (arg.Message)
                    {
                        case "AppClosed":
                            {                    
                                try
                                {
                                    param.StartPos = StartPos;
                                    param.EndPos = EndPos;
                                    param.CmdCount = CmdCount;
                                    param.CmdCount_Debug = CmdCount_Debug;
                                    param.CmdDistance = CmdDistance;
                                    param.CmdSpeed = CmdSpeed;
                                    param.ZeroValue = ZeroValue;
                                    param.IsDarkTheme = IsDarkTheme;
                                    param.CountLowLimit = CountLowLimit;
                                    param.CountHighLimit = CountHighLimit;
                                    param.DistanceLowLimit = DistanceLowLimit;
                                    param.DistanceHighLimit = DistanceHighLimit;
                                    param.SpeedLowLimit = SpeedLowLimit;
                                    param.SpeedHighLimit = SpeedHighLimit;
                                    string jsonString = JsonConvert.SerializeObject(param, Formatting.Indented);
                                    File.WriteAllText(System.IO.Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, "Param.json"), jsonString);                                    
                                }
                                catch (Exception ex)
                                {
                                    Debug.WriteLine(ex.Message);
                                }
                                if (MCUSerial.Instance.Connected)
                                {
                                    MCUSerial.Instance.WriteMCURegister(40001, 0);
                                }
                                if (PLCModbus.Instance.Connected)
                                {
                                    PLCModbus.Instance.WriteMCoil(12, false);
                                    PLCModbus.Instance.WriteMCoil(10, false);
                                    PLCModbus.Instance.WriteMCoil(1001, false);
                                }
                   
                                if (source1 != null)
                                {
                                    source1.Cancel();
                                }
                                if (source2 != null)
                                {
                                    source2.Cancel();
                                }
                            }
                            break;
                        case "AppLoaded":

                            OperateModeAciton(OpeMode);
                            if (PLCModbus.Instance.Connected)
                            {
                                PLCModbus.Instance.WriteMCoil(12, false);
                                PLCModbus.Instance.WriteMCoil(10, false);
                                ServoOnFlag = !PLCModbus.Instance.ReadMCoils(450, 1)[0];
                                {
                                    source1 = new CancellationTokenSource();
                                    CancellationToken token1 = source1.Token;
                                    Task.Run(() => Run(token1), token1);
                                }
                            }

                            if (MCUSerial.Instance.Connected)
                            {
                                MCUSerial.Instance.DataReceived += Instance_DataReceived;
                            }
                            if (PLCModbus.Instance.Connected && MCUSerial.Instance.Connected)
                            {
                                RunButtonIsEnable = true;                                
                                RadioButtonIsEnable1 = true;
                                PauseButtonIsEnable = true;
                            }
                            else
                            {
                                RunButtonIsEnable = false;
                                Run_DeubgButtonIsEnable = false;
                                PauseButtonIsEnable = false;
                                RadioButtonIsEnable1 = false;
                                RadioButtonIsEnable2 = false;
                            }
                            break;
                        case "Login":
                            Debug.WriteLine("Login");
                            if (PLCModbus.Instance.Connected && MCUSerial.Instance.Connected)
                            {
                                Run_DeubgButtonIsEnable = true;
                                if (!RunStartFlag)
                                {
                                    RadioButtonIsEnable2 = true;
                                }
                            }
                            isLogin = true;
                            break;
                        case "Logout":
                            Debug.WriteLine("Logout");
                            if (OpeMode == 2)
                            {
                                if (Run_DeubgStartFlag)
                                {
                                    PLCModbus.Instance.WriteMCoil(12, false);
                                    MCUSerial.Instance.WriteMCURegister(40001, 0);
                                    Run_DeubgStartFlag = false;
                                    RadioButtonIsEnable1 = true;
                                }
                                OperateModeAciton(0);
                                OpeMode = 0;
                            }
                            RadioButtonIsEnable2 = false;
                            if (SettingsViewVisibility == "Visible")
                            {
                                HomeViewVisibility = "Visible";
                                LifetimeViewVisibility = "Collapsed";
                                HistoryViewVisibility = "Collapsed";
                                SettingsViewVisibility = "Collapsed";
                            }
                            isLogin = false;
                            break;
                        case "ScreenShoot":
                            {
                                try
                                {                            
                                    string curScreenShotFile = Path.Combine(param.ScreenShotSavePath, "ScreenShot");
                                    if (!Directory.Exists(curScreenShotFile))
                                    {
                                        Directory.CreateDirectory(curScreenShotFile);
                                    }
                                    string ssfilename = "";
                                    if (HomeViewVisibility == "Visible")
                                    {
                                        if (TestModeVisibility == "Visible")
                                        {
                                            ssfilename = "弹力曲线";
                                        }
                                        else
                                        {
                                            ssfilename = "弹力曲线_调试";
                                        }
                                    }
                                    else if (LifetimeViewVisibility == "Visible")
                                    {
                                        ssfilename = "寿命曲线";
                                    }
                                    else if (HistoryViewVisibility == "Visible")
                                    {
                                        ssfilename = "历史曲线";
                                    }
                                    if (ssfilename != "")
                                    {
                                        // capture this window, and save it
                                        string fn = $"{DateTime.Now.ToString("yyyyMMddHHmmss")}_{ssfilename}.jpg";
                                        var pic = ScreenCapture.CaptureActiveWindow();
                                        pic.Save(Path.Combine(curScreenShotFile, fn), System.Drawing.Imaging.ImageFormat.Jpeg);
                                        pic.Dispose();
                                        await _dialogHostService.Question("信息", $"截图\"{fn}\"保存完成!", false);
                                    }
                                }
                                catch { }
                            }
                            break;
                        default:
                            break;
                    }
                }
                catch (Exception ex)
                {
                    Debug.WriteLine(ex.Message);
                }
                
            }, "App");
            HomeViewVisibility = "Visible";
            LifetimeViewVisibility = "Collapsed";
            HistoryViewVisibility = "Collapsed";
            SettingsViewVisibility = "Collapsed";
            aggregator.ResgiterMessage(async arg => {
                Debug.WriteLine(arg.Message);
                switch (arg.Message)
                {
                    case "Home":
                        HomeViewVisibility = "Visible";
                        LifetimeViewVisibility = "Collapsed";
                        HistoryViewVisibility = "Collapsed";
                        SettingsViewVisibility = "Collapsed";
                        break;
                    case "Lifetime":
                        HomeViewVisibility = "Collapsed";
                        LifetimeViewVisibility = "Visible";
                        HistoryViewVisibility = "Collapsed";
                        SettingsViewVisibility = "Collapsed";
                        break;
                    case "History":
                        HomeViewVisibility = "Collapsed";
                        LifetimeViewVisibility = "Collapsed";
                        HistoryViewVisibility = "Visible";
                        SettingsViewVisibility = "Collapsed";
                        break;
                    case "Settings":
                        if (isLogin)
                        {
                            HomeViewVisibility = "Collapsed";
                            LifetimeViewVisibility = "Collapsed";
                            HistoryViewVisibility = "Collapsed";
                            SettingsViewVisibility = "Visible";
                        }
                        else
                        {
                            await _dialogHostService.Question("提示", "请先登录", false);
                        }
                        break;
                    default:
                        break;
                }
            }, "Menu");
        }
        private void Instance_DataReceived(object sender, byte[] data,int length)
        {
            Task.Run(() => { Calc(data, length); });
        }
        #endregion
        #region 功能函数
        private void CalcKValue(List<MData> MDatas, int start, int end, int mCount1, double div1)
        {
            try
            {
                List<double> xlist = new List<double>();
                List<double> yList = new List<double>();
                List<MData> usedMData = new List<MData>();
                for (int j = start; j < end; j++)
                {
                    usedMData.Add(MDatas[j]);
                }
                List<MData> usedMData1 = new List<MData>();

                for (int ii = 0; ii < mCount1; ii++)
                {
                    var um1 = usedMData.Where(m => Math.Abs(m.Pos - ii * div1) <= 0.01).ToList();
                    if (um1.Any())
                    {
                        int index = 0;
                        if (um1.Count >= 2)
                        {
                            if (um1.Count % 2 == 0)
                            {
                                index = um1.Count / 2 - 1;
                            }
                            else
                            {
                                index = um1.Count / 2;
                            }
                        }
                        usedMData1.Add(um1[index]);
                        MDataStatisticsList.Add(new MData
                        {
                            Pos = ii * div1,
                            Force = um1[index].Force
                        });
                    }
                }
                if (usedMData1.Count >= 2)
                {
                    var temc = ((uint)((double)0xffffff / TotalCount * CurCount)).ToString("X8");
                    byte r = Convert.ToByte(temc.Substring(2, 2), 16);
                    byte g = Convert.ToByte(temc.Substring(4, 2), 16);
                    byte b = Convert.ToByte(temc.Substring(5, 2), 16);
                    PlotModel1.Series.Add(new LineSeries
                    {
                        LineStyle = LineStyle.Solid,
                        Color = OxyColor.FromRgb(r, g, b),
                        MarkerSize = 1,
                        MarkerStroke = OxyColors.Purple,
                        MarkerType = MarkerType.Plus,
                        TrackerFormatString = "{0}\n{1}: {2:0.000}\n{3}: {4:0.0}"
                    });
                    for (int j = 0; j < usedMData1.Count; j++)
                    {
                        xlist.Add(usedMData1[j].Pos);
                        yList.Add(usedMData1[j].Force);
                        var s = (LineSeries)PlotModel1.Series[PlotModel1.Series.Count - 1];
                        s.Points.Add(new DataPoint(usedMData1[j].Pos, usedMData1[j].Force));
                    }
                    PlotModel1.InvalidatePlot(true);
                    var p = Fit.Line(xlist.ToArray(), yList.ToArray());
                    KList.Add(Math.Round(p.B, 0));
                }
                else
                {
                    //Debug.WriteLine($"数值过少:{usedMData1.Count}");
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
            }
        }
        private void CalcKValue1(List<MData> MDatas, int start, int end)
        {
            try
            {
                List<MData> usedMData = new List<MData>();
                for (int j = start; j < end; j++)
                {
                    usedMData.Add(MDatas[j]);
                }
                for (int j = 0; j < usedMData.Count; j++)
                {
                    var s = (LineSeries)PlotModel1.Series[0];
                    s.Points.Add(new DataPoint(usedMData[j].Pos, usedMData[j].Force));
                }
                PlotModel1.InvalidatePlot(true);
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
            }
        }
        private void Run(CancellationToken token1)
        {
            bool _pAlarmFlag = false, _readyFlag = false;
            int _curCount = 0;
            while (true)
            {
                if (token1.IsCancellationRequested)
                {
                    return;
                }
                #region 读PLC数据
                if (PLCModbus.Instance.Connected)
                {
                    pAlarmFlag = PLCModbus.Instance.ReadMCoils(1000, 1)[0];
                    if (_pAlarmFlag != pAlarmFlag)
                    {
                        if (pAlarmFlag)
                        {
                            System.Windows.Application.Current.Dispatcher.Invoke(new Action(async () =>
                            {
                                var dialogResult = await _dialogHostService.Question("报警", "压力超范围", false);
                                PLCModbus.Instance.WriteMCoil(1000, false);
                            }));
                        }
                        _pAlarmFlag = pAlarmFlag;
                    }
                    //当前数量
                    var _CurCount = PLCModbus.Instance.ReadDRegisters(700, 2);
                    var _CurCountStr = _CurCount[1].ToString("X4") + _CurCount[0].ToString("X4");
                    CurCount = Convert.ToInt32(_CurCountStr, 16);
                    if (_curCount != CurCount)
                    {
                        if (TotalCount != 0)
                        {
                            FinishedClock = DateTime.Now.AddSeconds((TotalCount - CurCount) / CmdSpeed);
                        }
                        _curCount = CurCount;
                    }
                    if (TotalCount != 0)
                    {
                        ProgressBarValue = (double)CurCount / TotalCount * 100;
                    }
                    else
                    {
                        ProgressBarValue = 100;
                    }
                    readyFlag = PLCModbus.Instance.ReadMCoils(10, 1)[0];
                    if (_readyFlag != readyFlag)
                    {
                        if (readyFlag)
                        {
                            if (RunStartFlag)
                            {
                                PLCFinishFlag = true;
                            }
                            System.Threading.Thread.Sleep(1000);
                            MCUSerial.Instance.WriteMCURegister(40001, 0);
                            PLCModbus.Instance.WriteMCoil(12, false);
                            PLCModbus.Instance.WriteMCoil(10, false);
                        }
                        _readyFlag = readyFlag;
                    }
                }
                #endregion
                System.Threading.Thread.Sleep(200);
            }
        }
        private void DebugRun(CancellationToken token1)
        {
            Debug.WriteLine("DebugRun开始");
            while (true)
            {
                if (token1.IsCancellationRequested)
                {
                    Debug.WriteLine("DebugRun退出");
                    return;
                }
                WaitReceiveOne.Reset();
                MCUSerial.Instance.WriteMCURegister(40003, 1);
                WaitReceiveOne.WaitOne(3000);
                System.Threading.Thread.Sleep(100);
            }
        }
        private float GetFloatValueFromHexString(string hex)
        {
            //2143
            //string hex = "41F8BA4A";
            //string hex = "4036821F";
            byte[] raw = new byte[hex.Length / 2];
            for (int i = 0; i < raw.Length; i++)
            {
                // THEN DEPENDING ON ENDIANNESS
                //raw[i] = Convert.ToByte(hex.Substring(i * 2, 2), 16);
                // OR
                raw[raw.Length - i - 1] = Convert.ToByte(hex.Substring(i * 2, 2), 16);
            }
            float f = BitConverter.ToSingle(raw, 0);
            return f;
        }
        private async void OperateModeAciton(int mode)
        {
            recordZeroFlag = false;
            switch (mode)
            {
                case 0:
                    aggregator.SendMessage("测试模式");
                    TestModeVisibility = "Visible";
                    DebugModeVisibility = "Collapsed";
                    InstantValueVisibility = "Collapsed";

                    if (source2 != null)
                    {
                        source2.Cancel();
                        await Task.Delay(500);
                    }
                    PlotModel1 = new PlotModel { Title = "弹力曲线", TitleColor = foreground };
                    PlotModel1.PlotAreaBorderColor = foreground;
                    PlotModel1.TextColor = foreground;
                    PlotModel1.Axes.Add(new LinearAxis { Position = AxisPosition.Bottom,  MajorGridlineStyle = LineStyle.Dot, MajorGridlineColor = foreground, Title = "Pos",Minimum = 0,Maximum = EndPos - StartPos, TitleFontSize = 16, TicklineColor = foreground });
                    PlotModel1.Axes.Add(new LinearAxis { Position = AxisPosition.Left,  MajorGridlineStyle = LineStyle.Dot, MajorGridlineColor = foreground, Title = "Weight（gf）", TitleFontSize = 16, TicklineColor = foreground });
                    PlotModel1.InvalidatePlot(true);
                    break;
                case 2:

                    aggregator.SendMessage("调试模式");
                    TestModeVisibility = "Collapsed";
                    DebugModeVisibility = "Visible";
                    InstantValueVisibility = "Visible";
                    {
                        debugXAxisIndex = 0;
                        source2 = new CancellationTokenSource();
                        CancellationToken token1 = source2.Token;
                        PlotModel1 = new PlotModel();
                        PlotModel1.PlotAreaBorderColor = foreground;
                        PlotModel1.TextColor = foreground;
                        PlotModel1.Series.Add(new LineSeries { LineStyle = LineStyle.Solid, Color = OxyColors.SpringGreen, TrackerFormatString = "{0}\n{1}: {2:f0}\n{3}: {4:0.0}" });
                        PlotModel1.Axes.Add(new LinearAxis { Position = AxisPosition.Bottom,  MajorGridlineStyle = LineStyle.Dot, MajorGridlineColor = foreground, Title = "Index", TitleFontSize = 16, TicklineColor = foreground });
                        PlotModel1.Axes.Add(new LinearAxis { Position = AxisPosition.Left,  MajorGridlineStyle = LineStyle.Dot, MajorGridlineColor = foreground, Title = "Weight（gf）", TitleFontSize = 16, Minimum = -100, Maximum = 600, TicklineColor = foreground });
                        PlotModel1.InvalidatePlot(true);
                        Task.Run(() => DebugRun(token1), token1);
                    }
                    break;
                default:
                    break;
            }
        }
        private void Calc(byte[] data, int length)
        {
            if (length == 4)//
            {
                //前两个字节是编码器的值，后两个字节压力采集的AD值。都是高字节在前
                short poscount = BitConverter.ToInt16(data, 0);
                ushort forcead = BitConverter.ToUInt16(data, 2);
                double force = Math.Round(forcead / 4095.0 * param.WeightRange * 9.8 * 102, 1);
                if (recordZeroFlag)
                {
                    recordZeroFlag = false;
                    ZeroValue = force;
                }
                double pos = poscount / 900.0 * 2;
                InstantPos = pos;
                double force1 = force - ZeroValue;
                InstantForce = force1;
                WaitReceiveOne.Set();
                Task.Run(() => {
                    var s = (LineSeries)PlotModel1.Series[0];
                    if (s.Points.Count > 100)
                    {
                        s.Points.RemoveAt(0);
                    }
                    if (debugXAxisIndex > 1000)
                    {
                        debugXAxisIndex = 0;
                        s.Points.Clear();
                    }
                    s.Points.Add(new DataPoint(debugXAxisIndex, force1));
                    debugXAxisIndex++;
                    PlotModel1.InvalidatePlot(true);
                });

            }
            else if (length == 4000 && Run_DeubgStartFlag)
            {
                try
                {
                    var linecount = PlotModel1.Series.Count;
                    if (linecount > 1000)
                    {
                        PlotModel1.Series.Clear();
                        PlotModel1.InvalidatePlot(true);
                    }

                    List<MData> MDatas = new List<MData>();
                    for (int i = 0; i < 1000; i++)
                    {
                        short poscount = BitConverter.ToInt16(data, 0 + i * 4);
                        ushort forcead = BitConverter.ToUInt16(data, 2 + i * 4);
                        double pos = poscount / 900.0 * 2;
                        double force = Math.Round(forcead / 4095.0 * param.WeightRange * 9.8 * 102, 1);
                        double force1 = force - ZeroValue;
                        MDatas.Add(new MData
                        {
                            Pos = pos - StartPos,
                            Force = force1
                        });
                    }
                    if (MDatas.Count > 0)
                    {
                        int mCount1 = 10;
                        double div1 = (EndPos - StartPos) / (mCount1 - 1);
                        //分析波峰波谷
                        var bb = (from p in MDatas select p.Pos).ToArray();
                        List<int> picks = new List<int>();
                        List<int> throughs = new List<int>();
                        PeaksTroughsHelper.FindPeaksTroughs(bb, ref picks, ref throughs);

                        if (picks.Count == 0 && throughs.Count == 0)
                        {
                            if (bb[799] > bb[199])
                            {
                                CalcKValue(MDatas, 0, MDatas.Count - 1, mCount1, div1);
                            }
                        }
                        else if (picks.Count == 1 && throughs.Count == 0)
                        {
                            //Debug.WriteLine("From 0");
                            CalcKValue(MDatas, 0, picks[0], mCount1, div1);
                        }
                        else if (throughs.Count > 0)
                        {
                            if (picks.Count == 0)
                            {
                                //Debug.WriteLine("From End");
                                CalcKValue(MDatas, throughs[throughs.Count - 1], MDatas.Count - 1, mCount1, div1);
                            }
                            else
                            {
                                if (picks[0] < throughs[0])
                                {
                                    //Debug.WriteLine("From 1");
                                    CalcKValue(MDatas, 0, picks[0], mCount1, div1);
                                }
                                for (int i = 0; i < throughs.Count; i++)
                                {
                                    int p1 = picks.Where(n => n > throughs[i]).OrderBy(m => m).FirstOrDefault();
                                    if (p1 != 0)
                                    {
                                        //Debug.WriteLine("From Mid");
                                        CalcKValue(MDatas, throughs[i], p1, mCount1, div1);
                                    }
                                    else
                                    {
                                        //Debug.WriteLine("From End1");
                                        CalcKValue(MDatas, throughs[i], MDatas.Count - 1, mCount1, div1);
                                    }
                                }
                            }
                        }
                        if (KList.Count > 0)
                        {
                            PlotModel2.Axes.Clear();
                            PlotModel2.Series.Clear();
                            PlotModel2.InvalidatePlot(true);

                            var values = KList.ToArray();
                            var max = values.Max();
                            var min = values.Min();
                            if (max == min)
                            {
                                max = max + 1;
                                min = min - 1;
                            }
                            const int StepsNumber = 5;
                            double step = (max - min) / StepsNumber;
                            double mean = values.Average();
                            double deviationSq = values.Select(x => Math.Pow(x - mean, 2)).Average();
                            var bucketeer = new Dictionary<double, double>();

                            for (double curr = min; curr <= max; curr += step)
                            {
                                // Counting the values that can be put in the bucket and dividing them on values.Count()
                                var count = values.Where(x => x >= curr && x < curr + step).Count();
                                bucketeer.Add(curr, (double)count / values.Count());
                            }
                            // specify key and position
                            var barSeries = new BarSeries()
                            {
                                XAxisKey = "Value",
                                YAxisKey = "Category",
                                LabelPlacement = LabelPlacement.Inside,
                                LabelFormatString = "{0:.00}%"
                            };
                            var categoryAxis = new CategoryAxis() { Position = AxisPosition.Bottom, IsZoomEnabled = false, Key = "Category", MajorGridlineStyle = LineStyle.Solid, MajorGridlineColor = foreground, TicklineColor = foreground };
                            foreach (var pair in bucketeer.OrderBy(x => x.Key))
                            {
                                barSeries.Items.Add(new BarItem(pair.Value));
                                categoryAxis.Labels.Add(pair.Key.ToString("F0"));
                            }
                            var valueAxis = new LinearAxis { Position = AxisPosition.Left, IsZoomEnabled = false, Key = "Value", MajorGridlineStyle = LineStyle.Solid, MajorGridlineColor = foreground, TicklineColor = foreground };
                            PlotModel2.Axes.Add(valueAxis);
                            PlotModel2.Axes.Add(categoryAxis);
                            PlotModel2.Series.Add(barSeries);
                            PlotModel2.InvalidatePlot(true);
                        }

                        DataTable dtData = new DataTable();
                        dtData.Columns.Add("行程", typeof(string));

                        for (int k = 0; k < mCount1; k++)
                        {
                            var ms1 = MDataStatisticsList.Where(m => m.Pos == k * div1);
                            if (ms1.Any())
                            {
                                dtData.Columns.Add($"{k * div1:F2}mm", typeof(double));
                            }
                        }
                        {
                            //最大值
                            DataRow dataRow = dtData.NewRow();
                            dataRow["行程"] = "最大值(gf)";
                            for (int k = 0; k < mCount1; k++)
                            {
                                var ms1 = MDataStatisticsList.Where(m => m.Pos == k * div1);
                                if (ms1.Any())
                                {
                                    var maxv = ms1.Max(m => m.Force);
                                    dataRow[$"{k * div1:F2}mm"] = Math.Round(maxv, 2);
                                }
                            }
                            dtData.Rows.Add(dataRow);
                        }
                        {
                            //最小值
                            DataRow dataRow = dtData.NewRow();
                            dataRow["行程"] = "最小值(gf)";
                            for (int k = 0; k < mCount1; k++)
                            {
                                var ms1 = MDataStatisticsList.Where(m => m.Pos == k * div1);
                                if (ms1.Any())
                                {
                                    var minv = ms1.Min(m => m.Force);
                                    dataRow[$"{k * div1:F2}mm"] = Math.Round(minv, 2);
                                }
                            }
                            dtData.Rows.Add(dataRow);
                        }
                        {
                            //平均值
                            DataRow dataRow = dtData.NewRow();
                            dataRow["行程"] = "平均值(gf)";
                            for (int k = 0; k < mCount1; k++)
                            {
                                var ms1 = MDataStatisticsList.Where(m => m.Pos == k * div1);
                                if (ms1.Any())
                                {
                                    var avev = ms1.Average(m => m.Force);
                                    dataRow[$"{k * div1:F2}mm"] = Math.Round(avev, 2);
                                }
                            }
                            dtData.Rows.Add(dataRow);
                        }
                        System.Windows.Application.Current.Dispatcher.Invoke(new Action(() =>
                        {
                            PointData = dtData;
                        }));

                    }
                }
                catch { }
            }
            else if (length == 4000 && RunStartFlag)
            {
                try
                {
                    List<MData> MDatas = new List<MData>();
                    for (int i = 0; i < 1000; i++)
                    {
                        short poscount = BitConverter.ToInt16(data, 0 + i * 4);
                        ushort forcead = BitConverter.ToUInt16(data, 2 + i * 4);
                        double pos = Math.Round(poscount / 900.0 * 2, 3);
                        double force = Math.Round(forcead / 4095.0 * param.WeightRange * 9.8 * 102, 1);
                        double force1 = force - ZeroValue;
                        MDatas.Add(new MData
                        {
                            Pos = pos - StartPos,
                            Force = force1
                        });
                    }
                    if (MDatas.Count > 0)
                    {
                        //分析波峰波谷
                        var bb = (from p in MDatas select p.Pos).ToArray();
                        List<int> picks = new List<int>();
                        List<int> throughs = new List<int>();
                        PeaksTroughsHelper.FindPeaksTroughs(bb, ref picks, ref throughs);

                        if (picks.Count == 0 && throughs.Count == 0)
                        {
                            if (bb[799] > bb[199])
                            {
                                CalcKValue1(MDatas, 0, MDatas.Count - 1);
                            }
                        }
                        else if(picks.Count == 1 && throughs.Count == 0)
                        {
                            //Debug.WriteLine("From 0");
                            CalcKValue1(MDatas, 0, picks[0]);
                        }
                        else if (throughs.Count > 0)
                        {
                            if (picks.Count == 0)
                            {
                                //Debug.WriteLine("From End");
                                CalcKValue1(MDatas, throughs[throughs.Count - 1], MDatas.Count - 1);
                            }
                            else
                            {
                                if (picks[0] < throughs[0])
                                {
                                    //Debug.WriteLine("From 1");
                                    CalcKValue1(MDatas, 0, picks[0]);
                                }
                                for (int i = 0; i < throughs.Count; i++)
                                {
                                    int p1 = picks.Where(n => n > throughs[i]).OrderBy(m => m).FirstOrDefault();
                                    if (p1 != 0)
                                    {
                                        //Debug.WriteLine("From Mid");
                                        CalcKValue1(MDatas, throughs[i], p1);
                                    }
                                    else
                                    {
                                        //Debug.WriteLine("From End1");
                                        CalcKValue1(MDatas, throughs[i], MDatas.Count - 1);
                                    }
                                }
                            }
                        }
                    }
                }
                catch { }
                if (PlotModel1.Series.Count > 0)
                {
                    var pointcount = ((LineSeries)PlotModel1.Series[0]).Points.Count;
                    if (pointcount > 10000 || PLCFinishFlag)
                    {
                        int mCount1 = 10;
                        double div1 = (EndPos - StartPos) / (mCount1 - 1);
                        List<double> xlist = new List<double>();
                        List<double> yList = new List<double>();
                        List<MData> usedMData1 = new List<MData>();
                        var s = (LineSeries)PlotModel1.Series[0];
                        var points = s.Points;
                        for (int ii = 0; ii < mCount1; ii++)
                        {
                            var um1 = points.Where(m => Math.Abs(m.X - ii * div1) <= 0.01).ToList();
                            if (um1.Any())
                            {
                                double force = um1.Average(t => t.Y);
                                usedMData1.Add(new MData { Pos = ii * div1, Force = force });
                                MDataStatisticsList.Add(new MData
                                {
                                    Pos = ii * div1,
                                    Force = force
                                });
                            }
                        }

                        if (usedMData1.Count >= 2)
                        {
                            var temc = ((uint)((double)0xffffff / (TotalCount * 1.1) * CurCount)).ToString("X8");
                            byte r = Convert.ToByte(temc.Substring(2, 2), 16);
                            byte g = Convert.ToByte(temc.Substring(4, 2), 16);
                            byte b = Convert.ToByte(temc.Substring(5, 2), 16);
                            PlotModel100.Series.Add(new LineSeries
                            {
                                LineStyle = LineStyle.Solid,
                                Color = OxyColor.FromRgb(r, g, b),
                                MarkerSize = 1,
                                MarkerStroke = OxyColors.Purple,
                                MarkerType = MarkerType.Plus,
                                TrackerFormatString = "{0}\n{1}: {2:0.000}\n{3}: {4:0.0}"
                            });
                            if (PlotModel100.Series.Count > 200)
                            {
                                Random rd = new Random();
                                var index = rd.Next(9, 199);
                                PlotModel100.Series.RemoveAt(index);
                            }
                            for (int j = 0; j < usedMData1.Count; j++)
                            {
                                xlist.Add(usedMData1[j].Pos);
                                yList.Add(usedMData1[j].Force);
                                var s2 = (LineSeries)PlotModel100.Series[PlotModel100.Series.Count - 1];
                                s2.Points.Add(new DataPoint(usedMData1[j].Pos, usedMData1[j].Force));
                            }
                            System.Windows.Application.Current.Dispatcher.Invoke(new Action(() =>
                            {
                                var pngExporter = new OxyPlot.Wpf.PngExporter { Width = 1280, Height = 660 };
                                ImageSource100 = pngExporter.ExportToBitmap(PlotModel100);
                            }));
                            var p = Fit.Line(xlist.ToArray(), yList.ToArray());
                            KList.Add(Math.Round(p.B, 0));

                            double topva1 = yList.Max() + 10;
                            if (topva1 > topva)
                            {
                                topva = topva1;
                                PlotModel11.Axes[1].Maximum = topva;
                                PlotModel12.Axes[1].Maximum = topva;
                                PlotModel13.Axes[1].Maximum = topva;
                                PlotModel14.Axes[1].Maximum = topva;
                                PlotModel15.Axes[1].Maximum = topva;
                                PlotModel16.Axes[1].Maximum = topva;
                                PlotModel17.Axes[1].Maximum = topva;
                                PlotModel18.Axes[1].Maximum = topva;
                                PlotModel19.Axes[1].Maximum = topva;
                                PlotModel20.Axes[1].Maximum = topva;
                                PlotModel11.InvalidatePlot(true);
                                PlotModel12.InvalidatePlot(true);
                                PlotModel13.InvalidatePlot(true);
                                PlotModel14.InvalidatePlot(true);
                                PlotModel15.InvalidatePlot(true);
                                PlotModel16.InvalidatePlot(true);
                                PlotModel17.InvalidatePlot(true);
                                PlotModel18.InvalidatePlot(true);
                                PlotModel19.InvalidatePlot(true);
                                PlotModel20.InvalidatePlot(true);
                            }


                            double value1 = 0;
                            var v1 = usedMData1.FirstOrDefault(p => p.Pos == 0 * div1);
                            if (v1 != null)
                            {
                                value1 = v1.Force;
                                var s2 = (LineSeries)PlotModel11.Series[0];
                                s2.Points.Add(new DataPoint(CurCount, v1.Force));
                                if (s2.Points.Count <= 1)
                                {
                                    s2.Points.Add(new DataPoint(0, v1.Force));
                                }
                                PlotModel11.InvalidatePlot(true);
                            }
                            double value2 = 0;
                            var v2 = usedMData1.FirstOrDefault(p => p.Pos == 1 * div1);
                            if (v2 != null)
                            {
                                value2 = v2.Force;
                                var s2 = (LineSeries)PlotModel12.Series[0];
                                s2.Points.Add(new DataPoint(CurCount, v2.Force));
                                if (s2.Points.Count <= 1)
                                {
                                    s2.Points.Add(new DataPoint(0, v2.Force));
                                }
                                PlotModel12.InvalidatePlot(true);
                            }
                            double value3 = 0;
                            var v3 = usedMData1.FirstOrDefault(p => p.Pos == 2 * div1);
                            if (v3 != null)
                            {
                                value3 = v3.Force;
                                var s2 = (LineSeries)PlotModel13.Series[0];
                                s2.Points.Add(new DataPoint(CurCount, v3.Force));
                                if (s2.Points.Count <= 1)
                                {
                                    s2.Points.Add(new DataPoint(0, v3.Force));
                                }
                                PlotModel13.InvalidatePlot(true);
                            }
                            double value4 = 0;
                            var v4 = usedMData1.FirstOrDefault(p => p.Pos == 3 * div1);
                            if (v4 != null)
                            {
                                value4 = v4.Force;
                                var s2 = (LineSeries)PlotModel14.Series[0];
                                s2.Points.Add(new DataPoint(CurCount, v4.Force));
                                if (s2.Points.Count <= 1)
                                {
                                    s2.Points.Add(new DataPoint(0, v4.Force));
                                }
                                PlotModel14.InvalidatePlot(true);
                            }
                            double value5 = 0;
                            var v5 = usedMData1.FirstOrDefault(p => p.Pos == 4 * div1);
                            if (v5 != null)
                            {
                                value5 = v5.Force;
                                var s2 = (LineSeries)PlotModel15.Series[0];
                                s2.Points.Add(new DataPoint(CurCount, v5.Force));
                                if (s2.Points.Count <= 1)
                                {
                                    s2.Points.Add(new DataPoint(0, v5.Force));
                                }
                                PlotModel15.InvalidatePlot(true);
                            }
                            double value6 = 0;
                            var v6 = usedMData1.FirstOrDefault(p => p.Pos == 5 * div1);
                            if (v6 != null)
                            {
                                value6 = v6.Force;
                                var s2 = (LineSeries)PlotModel16.Series[0];
                                s2.Points.Add(new DataPoint(CurCount, v6.Force));
                                if (s2.Points.Count <= 1)
                                {
                                    s2.Points.Add(new DataPoint(0, v6.Force));
                                }
                                PlotModel16.InvalidatePlot(true);
                            }
                            double value7 = 0;
                            var v7 = usedMData1.FirstOrDefault(p => p.Pos == 6 * div1);
                            if (v7 != null)
                            {
                                value7 = v7.Force;
                                var s2 = (LineSeries)PlotModel17.Series[0];
                                s2.Points.Add(new DataPoint(CurCount, v7.Force));
                                if (s2.Points.Count <= 1)
                                {
                                    s2.Points.Add(new DataPoint(0, v7.Force));
                                }
                                PlotModel17.InvalidatePlot(true);
                            }
                            double value8 = 0;
                            var v8 = usedMData1.FirstOrDefault(p => p.Pos == 7 * div1);
                            if (v8 != null)
                            {
                                value8 = v8.Force;
                                var s2 = (LineSeries)PlotModel18.Series[0];
                                s2.Points.Add(new DataPoint(CurCount, v8.Force));
                                if (s2.Points.Count <= 1)
                                {
                                    s2.Points.Add(new DataPoint(0, v8.Force));
                                }
                                PlotModel18.InvalidatePlot(true);
                            }
                            double value9 = 0;
                            var v9 = usedMData1.FirstOrDefault(p => p.Pos == 8 * div1);
                            if (v9 != null)
                            {
                                value9 = v9.Force;
                                var s2 = (LineSeries)PlotModel19.Series[0];
                                s2.Points.Add(new DataPoint(CurCount, v9.Force));
                                if (s2.Points.Count <= 1)
                                {
                                    s2.Points.Add(new DataPoint(0, v9.Force));
                                }
                                PlotModel19.InvalidatePlot(true);
                            }
                            double value10 = 0;
                            var v10 = usedMData1.FirstOrDefault(p => p.Pos == 9 * div1);
                            if (v10 != null)
                            {
                                value10 = v10.Force;
                                var s2 = (LineSeries)PlotModel20.Series[0];
                                s2.Points.Add(new DataPoint(CurCount, v10.Force));
                                if (s2.Points.Count <= 1)
                                {
                                    s2.Points.Add(new DataPoint(0, v10.Force));
                                }
                                PlotModel20.InvalidatePlot(true);
                            }

                            //存CSV
                            try
                            {
                                using (var writer = new StreamWriter(Path.Combine(param.CsvSavePath, "Point", curCSVFileName), true, Encoding.UTF8))
                                using (var csv = new CsvWriter(writer, CultureInfo.InvariantCulture))
                                {

                                    var csvhead = new CSVItem
                                    {
                                        Index = CurCount,
                                        K = Math.Round(p.B, 0),
                                        Time = DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss"),
                                        Value1 = Math.Round(value1, 1),
                                        Value2 = Math.Round(value2, 1),
                                        Value3 = Math.Round(value3, 1),
                                        Value4 = Math.Round(value4, 1),
                                        Value5 = Math.Round(value5, 1),
                                        Value6 = Math.Round(value6, 1),
                                        Value7 = Math.Round(value7, 1),
                                        Value8 = Math.Round(value8, 1),
                                        Value9 = Math.Round(value9, 1),
                                        Value10 = Math.Round(value10, 1),
                                    };
                                    csv.WriteRecord(csvhead);
                                    csv.NextRecord();
                                }
                            }
                            catch { }
                            //存截图
                            //if ((DateTime.Now - lastScreenShotTime).TotalMinutes >= 30)
                            //{
                            //    Debug.WriteLine("截图");
                            //    Task.Run(async () => {
                            //        if (LifetimeViewVisibility != "Visible")
                            //        {
                            //            HomeViewVisibility = "Collapsed";
                            //            LifetimeViewVisibility = "Visible";
                            //            HistoryViewVisibility = "Collapsed";
                            //            SettingsViewVisibility = "Collapsed";
                            //        }
                            //        await Task.Delay(1000);
                            //        try
                            //        {
                            //            ScreenCapture sc = new ScreenCapture();
                            //            // capture this window, and save it
                            //            sc.CaptureScreenToFile(Path.Combine(curScreenShotFile, $"{DateTime.Now.ToString("yyyyMMddHHmmss")}.jpg"), System.Drawing.Imaging.ImageFormat.Jpeg);
                            //        }
                            //        catch { }
                            //        HomeViewVisibility = "Visible";
                            //        LifetimeViewVisibility = "Collapsed";
                            //        HistoryViewVisibility = "Collapsed";
                            //        SettingsViewVisibility = "Collapsed";
                            //    });
                            //    lastScreenShotTime = DateTime.Now;
                            //}
                        }
                        else
                        {
                            //Debug.WriteLine($"数值过少:{usedMData1.Count}");
                        }

                        if (KList.Count > 0)
                        {
                            PlotModel2.Axes.Clear();
                            PlotModel2.Series.Clear();
                            PlotModel2.InvalidatePlot(true);
                            var values = KList.ToArray();
                            const int StepsNumber = 5;
                            var max = values.Max();
                            var min = values.Min();
                            if (max == min)
                            {
                                max = max + 1;
                                min = min - 1;
                            }
                            double step = (max - min) / StepsNumber;
                            double mean = values.Average();
                            double deviationSq = values.Select(x => Math.Pow(x - mean, 2)).Average();
                            var bucketeer = new Dictionary<double, double>();

                            for (double curr = min; curr <= max; curr += step)
                            {
                                // Counting the values that can be put in the bucket and dividing them on values.Count()
                                var count = values.Where(x => x >= curr && x < curr + step).Count();
                                bucketeer.Add(curr, (double)count / values.Count());
                            }


                            // specify key and position
                            var barSeries = new BarSeries()
                            {
                                XAxisKey = "Value",
                                YAxisKey = "Category",
                                LabelPlacement = LabelPlacement.Inside,
                                LabelFormatString = "{0:.00}%"
                            };
                            var categoryAxis = new CategoryAxis() { Position = AxisPosition.Bottom, IsZoomEnabled = false, Key = "Category", MajorGridlineStyle = LineStyle.Solid, MajorGridlineColor = foreground, TicklineColor = foreground };
                            foreach (var pair in bucketeer.OrderBy(x => x.Key))
                            {
                                barSeries.Items.Add(new BarItem(pair.Value));
                                categoryAxis.Labels.Add(pair.Key.ToString("F0"));
                            }
                            var valueAxis = new LinearAxis { Position = AxisPosition.Left, IsZoomEnabled = false, Key = "Value", MajorGridlineStyle = LineStyle.Solid, MajorGridlineColor = foreground, TicklineColor = foreground };
                            PlotModel2.Axes.Add(valueAxis);
                            PlotModel2.Axes.Add(categoryAxis);
                            PlotModel2.Series.Add(barSeries);
                            PlotModel2.InvalidatePlot(true);
                        }

                        DataTable dtData = new DataTable();
                        dtData.Columns.Add("行程", typeof(string));

                        for (int k = 0; k < mCount1; k++)
                        {
                            var ms1 = MDataStatisticsList.Where(m => m.Pos == k * div1);
                            if (ms1.Any())
                            {
                                dtData.Columns.Add($"{k * div1:F2}mm", typeof(double));
                            }
                        }
                        {
                            //最大值
                            DataRow dataRow = dtData.NewRow();
                            dataRow["行程"] = "最大值(gf)";
                            for (int k = 0; k < mCount1; k++)
                            {
                                var ms1 = MDataStatisticsList.Where(m => m.Pos == k * div1);
                                if (ms1.Any())
                                {
                                    var maxv = ms1.Max(m => m.Force);
                                    dataRow[$"{k * div1:F2}mm"] = Math.Round(maxv, 2);
                                }
                            }
                            dtData.Rows.Add(dataRow);
                        }
                        {
                            //最小值
                            DataRow dataRow = dtData.NewRow();
                            dataRow["行程"] = "最小值(gf)";
                            for (int k = 0; k < mCount1; k++)
                            {
                                var ms1 = MDataStatisticsList.Where(m => m.Pos == k * div1);
                                if (ms1.Any())
                                {
                                    var minv = ms1.Min(m => m.Force);
                                    dataRow[$"{k * div1:F2}mm"] = Math.Round(minv, 2);
                                }
                            }
                            dtData.Rows.Add(dataRow);
                        }
                        {
                            //平均值
                            DataRow dataRow = dtData.NewRow();
                            dataRow["行程"] = "平均值(gf)";
                            for (int k = 0; k < mCount1; k++)
                            {
                                var ms1 = MDataStatisticsList.Where(m => m.Pos == k * div1);
                                if (ms1.Any())
                                {
                                    var avev = ms1.Average(m => m.Force);
                                    dataRow[$"{k * div1:F2}mm"] = Math.Round(avev, 2);
                                }
                            }
                            dtData.Rows.Add(dataRow);
                        }
                        PointData = dtData;
                        if (!PLCFinishFlag)
                        {
                            var s1 = (LineSeries)PlotModel1.Series[0];
                            s1.Points.Clear();
                            PlotModel1.InvalidatePlot(true);
                        }
                        //PLCFinishFlag = false;
                    }
                }
            }
        }
        void LoadParam()
        {
            try
            {
                //Json序列化，从文件读取
                string jsonString = File.ReadAllText(System.IO.Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, "Param.json"));
                param = JsonConvert.DeserializeObject<Param>(jsonString);
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
            }
        }
        private void Init10Oxy(double start,double div)
        {
            PlotModel11 = new PlotModel() { Title = $"{start + div * 0:F2}mm寿命曲线", TitleColor = foreground };
            PlotModel11.PlotAreaBorderColor = foreground;
            PlotModel11.TextColor = foreground;
            PlotModel11.Axes.Add(new LinearAxis { Position = AxisPosition.Bottom,  MajorGridlineStyle = LineStyle.Dot, MajorGridlineColor = foreground, Title = "Index(sec)", TitleFontSize = 16, TicklineColor = foreground });
            PlotModel11.Axes.Add(new LinearAxis { Position = AxisPosition.Left,  MajorGridlineStyle = LineStyle.Dot, MajorGridlineColor = foreground, Title = "Weight（gf）",Minimum = -10, Maximum = 200, TitleFontSize = 16, TicklineColor = foreground });
            PlotModel11.Series.Add(new LineSeries { LineStyle = LineStyle.Solid, Color = OxyColors.SpringGreen, TrackerFormatString = "{0}\n{1}: {2:f0}\n{3}: {4:0.0}" });
            PlotModel11.InvalidatePlot(true);

            PlotModel12 = new PlotModel() { Title = $"{start + div * 1:F2}mm", TitleColor = foreground };
            PlotModel12.PlotAreaBorderColor = foreground;
            PlotModel12.TextColor = foreground;            
            PlotModel12.Axes.Add(new LinearAxis { Position = AxisPosition.Bottom,  MajorGridlineStyle = LineStyle.Dot, MajorGridlineColor = foreground, Title = "Index(sec)", TitleFontSize = 16, TicklineColor = foreground });
            PlotModel12.Axes.Add(new LinearAxis { Position = AxisPosition.Left,  MajorGridlineStyle = LineStyle.Dot, MajorGridlineColor = foreground, Title = "Weight（gf）", Minimum = -10, Maximum = 200, TitleFontSize = 16, TicklineColor = foreground });
            PlotModel12.Series.Add(new LineSeries { LineStyle = LineStyle.Solid, Color = OxyColors.SpringGreen, TrackerFormatString = "{0}\n{1}: {2:f0}\n{3}: {4:0.0}" });
            PlotModel12.InvalidatePlot(true);

            PlotModel13 = new PlotModel() { Title = $"{start + div * 2:F2}mm", TitleColor = foreground };
            PlotModel13.PlotAreaBorderColor = foreground;
            PlotModel13.TextColor = foreground;            
            PlotModel13.Axes.Add(new LinearAxis { Position = AxisPosition.Bottom,  MajorGridlineStyle = LineStyle.Dot, MajorGridlineColor = foreground, Title = "Index(sec)", TitleFontSize = 16, TicklineColor = foreground });
            PlotModel13.Axes.Add(new LinearAxis { Position = AxisPosition.Left,  MajorGridlineStyle = LineStyle.Dot, MajorGridlineColor = foreground, Title = "Weight（gf）", Minimum = -10, Maximum = 200, TitleFontSize = 16, TicklineColor = foreground });
            PlotModel13.Series.Add(new LineSeries { LineStyle = LineStyle.Solid, Color = OxyColors.SpringGreen, TrackerFormatString = "{0}\n{1}: {2:f0}\n{3}: {4:0.0}" });
            PlotModel13.InvalidatePlot(true);

            PlotModel14 = new PlotModel() { Title = $"{start + div * 3:F2}mm", TitleColor = foreground };
            PlotModel14.PlotAreaBorderColor = foreground;
            PlotModel14.TextColor = foreground;            
            PlotModel14.Axes.Add(new LinearAxis { Position = AxisPosition.Bottom,  MajorGridlineStyle = LineStyle.Dot, MajorGridlineColor = foreground, Title = "Index(sec)", TitleFontSize = 16, TicklineColor = foreground });
            PlotModel14.Axes.Add(new LinearAxis { Position = AxisPosition.Left,  MajorGridlineStyle = LineStyle.Dot, MajorGridlineColor = foreground, Title = "Weight（gf）", Minimum = -10, Maximum = 200, TitleFontSize = 16, TicklineColor = foreground });
            PlotModel14.Series.Add(new LineSeries { LineStyle = LineStyle.Solid, Color = OxyColors.SpringGreen, TrackerFormatString = "{0}\n{1}: {2:f0}\n{3}: {4:0.0}" });
            PlotModel14.InvalidatePlot(true);

            PlotModel15 = new PlotModel() { Title = $"{start + div * 4:F2}mm", TitleColor = foreground };
            PlotModel15.PlotAreaBorderColor = foreground;
            PlotModel15.TextColor = foreground;           
            PlotModel15.Axes.Add(new LinearAxis { Position = AxisPosition.Bottom,  MajorGridlineStyle = LineStyle.Dot, MajorGridlineColor = foreground, Title = "Index(sec)", TitleFontSize = 16, TicklineColor = foreground });
            PlotModel15.Axes.Add(new LinearAxis { Position = AxisPosition.Left,  MajorGridlineStyle = LineStyle.Dot, MajorGridlineColor = foreground, Title = "Weight（gf）", Minimum = -10, Maximum = 200, TitleFontSize = 16, TicklineColor = foreground });
            PlotModel15.Series.Add(new LineSeries { LineStyle = LineStyle.Solid, Color = OxyColors.SpringGreen, TrackerFormatString = "{0}\n{1}: {2:f0}\n{3}: {4:0.0}" });
            PlotModel15.InvalidatePlot(true);

            PlotModel16 = new PlotModel() { Title = $"{start + div * 5:F2}mm", TitleColor = foreground };
            PlotModel16.PlotAreaBorderColor = foreground;
            PlotModel16.TextColor = foreground;            
            PlotModel16.Axes.Add(new LinearAxis { Position = AxisPosition.Bottom,  MajorGridlineStyle = LineStyle.Dot, MajorGridlineColor = foreground, Title = "Index(sec)", TitleFontSize = 16, TicklineColor = foreground });
            PlotModel16.Axes.Add(new LinearAxis { Position = AxisPosition.Left,  MajorGridlineStyle = LineStyle.Dot, MajorGridlineColor = foreground, Title = "Weight（gf）", Minimum = -10, Maximum = 200, TitleFontSize = 16, TicklineColor = foreground });
            PlotModel16.Series.Add(new LineSeries { LineStyle = LineStyle.Solid, Color = OxyColors.SpringGreen, TrackerFormatString = "{0}\n{1}: {2:f0}\n{3}: {4:0.0}" });
            PlotModel16.InvalidatePlot(true);

            PlotModel17 = new PlotModel() { Title = $"{start + div * 6:F2}mm", TitleColor = foreground };
            PlotModel17.PlotAreaBorderColor = foreground;
            PlotModel17.TextColor = foreground;
            PlotModel17.Axes.Add(new LinearAxis { Position = AxisPosition.Bottom,  MajorGridlineStyle = LineStyle.Dot, MajorGridlineColor = foreground, Title = "Index(sec)", TitleFontSize = 16, TicklineColor = foreground });
            PlotModel17.Axes.Add(new LinearAxis { Position = AxisPosition.Left,  MajorGridlineStyle = LineStyle.Dot, MajorGridlineColor = foreground, Title = "Weight（gf）", Minimum = -10, Maximum = 200, TitleFontSize = 16, TicklineColor = foreground });
            PlotModel17.Series.Add(new LineSeries { LineStyle = LineStyle.Solid, Color = OxyColors.SpringGreen, TrackerFormatString = "{0}\n{1}: {2:f0}\n{3}: {4:0.0}" });
            PlotModel17.InvalidatePlot(true);

            PlotModel18 = new PlotModel() { Title = $"{start + div * 7:F2}mm", TitleColor = foreground };
            PlotModel18.PlotAreaBorderColor = foreground;
            PlotModel18.TextColor = foreground;
            PlotModel18.Axes.Add(new LinearAxis { Position = AxisPosition.Bottom,  MajorGridlineStyle = LineStyle.Dot, MajorGridlineColor = foreground, Title = "Index(sec)", TitleFontSize = 16, TicklineColor = foreground });
            PlotModel18.Axes.Add(new LinearAxis { Position = AxisPosition.Left,  MajorGridlineStyle = LineStyle.Dot, MajorGridlineColor = foreground, Title = "Weight（gf）", Minimum = -10, Maximum = 200, TitleFontSize = 16, TicklineColor = foreground });
            PlotModel18.Series.Add(new LineSeries { LineStyle = LineStyle.Solid, Color = OxyColors.SpringGreen, TrackerFormatString = "{0}\n{1}: {2:f0}\n{3}: {4:0.0}" });
            PlotModel18.InvalidatePlot(true);

            PlotModel19 = new PlotModel() { Title = $"{start + div * 8:F2}mm", TitleColor = foreground };
            PlotModel19.PlotAreaBorderColor = foreground;
            PlotModel19.TextColor = foreground;
            PlotModel19.Axes.Add(new LinearAxis { Position = AxisPosition.Bottom,  MajorGridlineStyle = LineStyle.Dot, MajorGridlineColor = foreground, Title = "Index(sec)", TitleFontSize = 16, TicklineColor = foreground });
            PlotModel19.Axes.Add(new LinearAxis { Position = AxisPosition.Left,  MajorGridlineStyle = LineStyle.Dot, MajorGridlineColor = foreground, Title = "Weight（gf）", Minimum = -10, Maximum = 200, TitleFontSize = 16, TicklineColor = foreground });
            PlotModel19.Series.Add(new LineSeries { LineStyle = LineStyle.Solid, Color = OxyColors.SpringGreen, TrackerFormatString = "{0}\n{1}: {2:f0}\n{3}: {4:0.0}" });
            PlotModel19.InvalidatePlot(true);

            PlotModel20 = new PlotModel() { Title = $"{start + div * 9:F2}mm", TitleColor = foreground };
            PlotModel20.PlotAreaBorderColor = foreground;
            PlotModel20.TextColor = foreground;
            PlotModel20.Axes.Add(new LinearAxis { Position = AxisPosition.Bottom,  MajorGridlineStyle = LineStyle.Dot, MajorGridlineColor = foreground, Title = "Index(sec)", TitleFontSize = 16, TicklineColor = foreground });
            PlotModel20.Axes.Add(new LinearAxis { Position = AxisPosition.Left,  MajorGridlineStyle = LineStyle.Dot, MajorGridlineColor = foreground, Title = "Weight（gf）", Minimum = -10, Maximum = 200, TitleFontSize = 16, TicklineColor = foreground });
            PlotModel20.Series.Add(new LineSeries { LineStyle = LineStyle.Solid, Color = OxyColors.SpringGreen, TrackerFormatString = "{0}\n{1}: {2:f0}\n{3}: {4:0.0}" });
            PlotModel20.InvalidatePlot(true);
        }
        private void ModifyTheme(Action<ITheme> modificationAction)
        {
            var paletteHelper = new PaletteHelper();
            ITheme theme = paletteHelper.GetTheme();
            modificationAction?.Invoke(theme);
            paletteHelper.SetTheme(theme);
        }
        private void ApplyTheme(bool r)
        {
            foreground = r ? OxyColor.FromRgb(32, 32, 32) : OxyColors.White;
            ChangePlotModelColor(PlotModel1, foreground);
            ChangePlotModelColor(PlotModel2, foreground);
            ChangePlotModelColor(PlotModel11, foreground);
            ChangePlotModelColor(PlotModel12, foreground);
            ChangePlotModelColor(PlotModel13, foreground);
            ChangePlotModelColor(PlotModel14, foreground);
            ChangePlotModelColor(PlotModel15, foreground);
            ChangePlotModelColor(PlotModel16, foreground);
            ChangePlotModelColor(PlotModel17, foreground);
            ChangePlotModelColor(PlotModel18, foreground);
            ChangePlotModelColor(PlotModel19, foreground);
            ChangePlotModelColor(PlotModel20, foreground);
            ChangePlotModelColor(PlotModel100, foreground);
            if (PlotModel100 != null)
            {
                var pngExporter = new OxyPlot.Wpf.PngExporter { Width = 1280, Height = 660 };
                ImageSource100 = pngExporter.ExportToBitmap(PlotModel100);
            }
        }
        private void ChangePlotModelColor(PlotModel model, OxyColor color)
        {
            if (model != null)
            {
                model.TitleColor = color;
                model.PlotAreaBorderColor = color;
                model.TextColor = color;
                foreach (var axis in model.Axes)
                {
                    axis.MajorGridlineColor = color;
                    axis.TicklineColor = color;
                }
                model.InvalidatePlot(true);
            }
        }
        #endregion
    }
    public class MData
    {
        public double Pos { get; set; }
        public double Force { get; set; }
    }
    class CSVItem
    {
        public int Index { get; set; }
        public double Value1 { get; set; }
        public double Value2 { get; set; }
        public double Value3 { get; set; }
        public double Value4 { get; set; }
        public double Value5 { get; set; }
        public double Value6 { get; set; }
        public double Value7 { get; set; }
        public double Value8 { get; set; }
        public double Value9 { get; set; }
        public double Value10 { get; set; }
        public double K { get; set; }
        public string Time { get; set; }
    }
}
